import 'package:dio/dio.dart';
import 'package:flutterclue/http_util/base_http.dart';
import 'base_http.dart';
import 'dart:convert';
import 'constant_url.dart';
import 'dart:async';
import 'package:crypto/crypto.dart';
import 'package:flutterclue/mvp/mode/base_mode.dart';
import 'package:flutterclue/utils/SharePreferensUtil.dart';
import 'package:flutter/material.dart';

class HttpUtilsByDio extends HttpInterface {
  static HttpUtilsByDio _httpUtilsByDio = new HttpUtilsByDio();

  static Dio _dio;



  static HttpUtilsByDio initInstance() {
    if (_dio == null) {
      _dio = new Dio();
      _dio.options.baseUrl = ApiUrl.BASE_DEBUG_URL;
      _dio.options.connectTimeout = 10000;
      _dio.options.connectTimeout = 10000;
      _dio.interceptor.request.onSend = (Options options) {
        // 在请求被发送之前做一些事情
        return options; //continue
        // 如果你想完成请求并返回一些自定义数据，可以返回一个`Response`对象或返回`dio.resolve(data)`。
        // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义数据data.
        // 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象，或返回`dio.reject(errMsg)`，
        // 这样请求将被中止并触发异常，上层catchError会被调用。
      };
      _dio.interceptor.response.onSuccess = (Response response) {
        // 在返回响应数据之前做一些预处理
        return response; // continue
      };
      _dio.interceptor.response.onError = (DioError e) {
        // 当请求失败时做一些预处理
        return e; //continue
      };
    }
    return _httpUtilsByDio;
  }

  @override
  Future<BaseBean> post(
      {String url,
      Map<String, Object> headers,
      Map<String, Object> params,
      onSelect}) async {
    Map<String, Object> map = await excuteBody(params);
    Response response =
        await _dio.post(url, data: json.encode(map)).catchError((error) {
      interceptorDioError(onSelect, error);
    });
    BaseBean baseBean = BaseBean.fromParams();
    baseBean.Message = response.data["Message"];
    baseBean.Code = response.data["Code"];
    baseBean.Data = response.data["Data"];
    return baseBean;
  }

  ///拦截错误信息
  void interceptorDioError(ValueChanged<String> onSelect, DioError e) {
    switch (e.type) {
      case DioErrorType.DEFAULT:
        onSelect("暂无网络或连接服务器失败");
        break;
      case DioErrorType.CONNECT_TIMEOUT:
        onSelect("连接服务器超时");
        break;
      case DioErrorType.CANCEL:
        onSelect("请求撤回");
        break;
      case DioErrorType.RECEIVE_TIMEOUT:
        onSelect("接收数据超时");
        break;
      case DioErrorType.RESPONSE:
        onSelect("${e.message}");
        break;
      default:
        onSelect("${e.message}");
        break;
    }
  }

  Future excuteBody(Map<String, Object> params) async {
    String token =
        await SharePreferencesUtil.getString(SharePreferencesUtil.TOKEN);
    if (token != null && token.toString().isNotEmpty) {
      params["Token"] = token.toString();
    }
    params["LoginType"] = "Android";
    Map<String, String> paramsBody = new Map();
    params.forEach((key, value) {
      paramsBody[key] = value;
    });
    params["KeyCode"] = ApiUrl.KeyCode;
    paramsBody["Version"] = "1.0.0";
    paramsBody["SecCode"] = encryption(sortStringArray(params));
    return paramsBody;
  }

  ///参数排序
  List<String> sortStringArray(Map<String, Object> hm) {
    List<String> list = new List();
    hm.forEach((key, value) {
      String content = key + "=" + value + "&";
      list.add(content);
    });
    list.sort((a, b) => a.toUpperCase().compareTo(b.toUpperCase()));
    return list;
  }

  ///参数MD5
  String encryption(List<String> list) {
    StringBuffer plainText = new StringBuffer();
    list.forEach((value) {
      plainText.write(value);
    });
    var content = new Utf8Encoder()
        .convert(plainText.toString().substring(0, plainText.length - 1));
    Digest digest = md5.convert(content);
    List<int> list1 = digest.bytes;
    StringBuffer buf = new StringBuffer();
    list1.forEach((digest) {
      if (digest < 0) digest += 256;
      if (digest < 16) buf.write("0");
      buf.write(digest.toInt().toRadixString(16));
    });
    return buf.toString();
  }

  @override
  Future<BaseBean> get(
      {String url,
      Map<String, Object> headers,
      Map<String, Object> params,
      onSelect}) {
    // TODO: implement get
    return null;
  }
}
